package com.charlygao.script;

import java.awt.AWTException;
import java.awt.event.KeyEvent;
import java.lang.invoke.ConstantCallSite;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
import java.util.zip.Inflater;

import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;
import org.omg.IOP.MultipleComponentProfileHelper;

import com.charlygao.Command;
import com.charlygao.HttpUtil;
import com.charlygao.MainWindow;
import com.charlygao.PropertyHelper;
import com.charlygao.entity.NameMap;
import com.charlygao.entity.Ship;
import com.charlygao.entity.TurnRule;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.win32.W32APIOptions;

public class Kcs implements Runnable
{
	public String memOffset;
	public String serverIp;
	public String windowName;
	public int auto_mode;
	public int auto_kira;
	public int auto_res;
	public int auto_mission;
	public int auto_steel;
	public int select_mode;
	public String auto_map;
	public String res_map;
	public int [] fleet_mission_map = new int[5];
	public int [] fleet_mission_kira = new int[5];
	public TurnRule rules [] = new TurnRule[6];
	public TurnRule kiraRule = new TurnRule();
	public TurnRule resRule = new TurnRule();
	public TurnRule feedRule = new TurnRule();
	public TurnRule missionRule [][] = new TurnRule[40][6];
	public HashMap<Integer, Ship> ships = new HashMap<Integer, Ship>();
	public int [] ndockStatus = new int[5];
	public int [] [] fleetData = new int[5][6];
	public int fleetIndex, mission_id;
	ArrayList<BasicNameValuePair> params;
	public String referer;
	public String flashVersion;
	String response;
	public int resource[] = new int[7];
	public int wldata[] = new int[3];
	public long startTime;
	public int startResource[] = new int[7];
	public int startWldata[] = new int[3];
	
	public int MODE_KIRA = 1;
	public int MODE_RES = 2;
	public int MODE_MISSION = 3;
	public int MODE_LEVEL = 4;
	public int MODE_STEEL = 5;
	
	User32 user32;
	Command command;
	HWND rhwnd;
	HWND hwnd;
	public String token;
	BigInteger portNum;
	BigInteger millNum;
	Random random = new Random();
	
	public Kcs()
	{
		serverIp = "http://125.6.187.253/";
		windowName = "提督業も忙しい！";
		portNum = new BigInteger("1957686108662303498823"); // 04/27 21:27:40 sync ok
		millNum = new BigInteger("1398353771942");
		
		NameMap.init();
		for (int i = 0; i < 6; i++)
			rules[i] = new TurnRule();
		
		auto_map = "3-2";
		// 练级配置
		rules[0].lvGate = 99;
		rules[0].condGate = 40;
		rules[0].shipSet("飞龙");
		rules[1].condGate = 40;
		rules[1].shipSet("岛风, 雪风, 利根, 筑摩, 羽黑, 夕立, 时雨");
		rules[2].condGate = 40;
		rules[2].shipSet("比睿, 雾岛, 长门, 陆奥, 日向, 伊势");
		rules[3].condGate = 0;
		rules[3].shipSet("长良");
		rules[4].condGate = 0;
		rules[4].shipSet("千代田");
		//rules[5].condGate = 40;
		//rules[5].shipSet("i19-2, i19-3, i19-4, i19-5, i8-3, i8-4, i8-5, i8-2");
		rules[5].condGate = 0;
		rules[5].shipSet("m8, m9, m3, m4, m5, m6, m7, m2");
	
		
		String ddString = "白露, 村雨, 凉风, 五月雨, " + // -白露 -村雨
						  "绫波, 敷波, 胧, 曙, 潮, 涟, " +
						  "阳炎, 不知火, 黑潮, 舞风, 浜风, 浦风, 初风, 谷风, " + // -阳炎 -不知火
						  "吹雪, 白雪, 深雪, 初雪, 从云, 磯波, " + 
						  "朝潮, 荒潮, 满潮, 大潮, 霞, 霰, " +
						  "晓, 雷, 电, " +
						  "夕云, 秋云, 卷云, 长波, " +
						  "初春, 初霜, 子日, 若叶, " + 
						  "睦月, 如月, 文月, 望月, 皋月, 长月, 菊月, 三日月, 弥生, 卯月, " + // -睦月
						  "Z1, Z3";
		
		String clString = "多摩, 鬼怒, 球磨, 天龙, 龙田";
		
		// 刷闪配置
		kiraRule.lvGate = 50;
		kiraRule.condGate = 74;
		kiraRule.shipSet(clString + "," + ddString);
		
		// 偷油配置
		res_map = "2-3";
		resRule.condGate = 40;
		resRule.hpGate = 0.6;
		resRule.shipSet("i168-6, i168-2, i168-3, i168-4, i168-5");
		
		
		
		// 全自动刷闪远征
		for (int i = 0 ; i < 6; i++)
		{
			missionRule[2][i] = new TurnRule();
			missionRule[2][i].lvGate = 50;
			missionRule[2][i].condGate = 50;
			missionRule[2][i].shipSet(ddString);
			
			missionRule[3][i] = new TurnRule();
			missionRule[3][i].lvGate = 50;
			missionRule[3][i].condGate = 50;
			missionRule[3][i].shipSet(ddString);
			
			missionRule[5][i] = new TurnRule();
			missionRule[5][i].lvGate = 50;
			missionRule[5][i].condGate = 50;
			missionRule[5][i].shipSet(ddString);
			
			missionRule[6][i] = new TurnRule();
			missionRule[6][i].lvGate = 50;
			missionRule[6][i].condGate = 50;
			missionRule[6][i].shipSet(ddString);
			
			missionRule[8][i] = new TurnRule();
			missionRule[8][i].lvGate = 50;
			missionRule[8][i].condGate = 50;
			missionRule[8][i].shipSet(ddString);
		}
		missionRule[5][0] = new TurnRule();
		missionRule[5][0].lvGate = 50;
		missionRule[5][0].condGate = 50;
		missionRule[5][0].shipSet(clString);
		
		// 驱逐捞钢配置
		feedRule.condGate = 0;
		
	}
	
	@Override
	public void run() 
	{
		try 
		{
			HttpUtil.init(serverIp);
			user32 = (User32) Native.loadLibrary("User32", User32.class, W32APIOptions.UNICODE_OPTIONS);
			command = new Command();
			rhwnd = user32.FindWindow(null, windowName);
			hwnd = rhwnd;
			System.out.println(hwnd);
			for (int i = 0; i < 3; i++)
			{
				user32.EnumChildWindows(hwnd, new User32.WNDENUMPROC() {
					@Override
					public boolean callback(HWND arg0, Pointer arg1) {
						hwnd = arg0;
	                    return true;
					}
	            }, null);
			}
			MainWindow.log(hwnd.toString());
		} 
		catch (AWTException e) {
			e.printStackTrace();
		}
		/*
		System.out.println(getPortTime());
		MainWindow.display.asyncExec(new Runnable() {
			public void run() {
				MainWindow.txtStaticTokenAddr.setText(memOffset);
			}
		});*/
		
		boolean mainReady = false;
		while (true)
		{
			try
			{
				System.out.println(token);
				rDelay(500);
				
				// 检查可解体船只
				checkFeedShips();
				
				System.out.println("检查舰队远征状态");
				MainWindow.log("检查舰队远征状态");
				if (!waitForColor("FFC0BD1D", 716, 83, 49, 228))
				{
					reconnect(1);
					continue;
				}
				System.out.println("检查中");
				MainWindow.log("检查中");
				for (fleetIndex = 2; fleetIndex < 5; fleetIndex++)
				{
					bgLeftClick(150 + (fleetIndex - 1) * 30, 120);
					rDelay(2000);
					if (!command.isColor(hwnd, "FFBE858B", 272, 156) && fleet_mission_map[fleetIndex] != 0)
					{
						System.out.println("舰队" + fleetIndex + " 远征准备出发。");
						MainWindow.log("舰队" + fleetIndex + " 远征准备出发。");
						rDelay(2000);
						bgLeftClick(120, 120);
						rDelay(1500);
						System.out.println("正在补给");
						MainWindow.log("正在补给");
						bgLeftClick(700, 440);
						rDelay(2500);
						break;
					}
				}
				mission_id = 0;
				if (fleetIndex < 5)
				{
					mission_id = fleet_mission_map[fleetIndex];
					// 全闪远征逻辑
					if (fleet_mission_kira[fleetIndex] == 1 && auto_mission == 1 && !command.isColor(hwnd, "FFBE858B", 272, 156))
					{
						System.out.println("正在准备远征舰队阵容");
						MainWindow.log("正在准备远征舰队");
						mainReady = checkAttack(true, MODE_MISSION);
						if (mainReady)
						{
							System.out.println("***远征舰队准备完毕，可以出发。***");
							MainWindow.log("***远征准备完毕***");
						}
					}
				}
				
				// 自动练级逻辑
				if (mission_id == 0 && ((auto_mode == 1) || (auto_kira == 1) || (auto_res == 1) || (auto_steel == 1)))
				{
					fleetIndex = 1;
					bgLeftClick(150, 120);
					rDelay(2000);
					bgLeftClick(120, 120);
					rDelay(2000);
					bgLeftClick(700, 440);
					rDelay(2000);
					System.out.println("正在准备主力舰队阵容");
					MainWindow.log("正在准备主力舰队");
					//rDelay(2000);
					refreshInfo();
					//rDelay(2000);
					if (auto_mode == 1)
					{
						select_mode = MODE_LEVEL;
						mainReady = checkAttack(true, select_mode);
					}
					if (auto_kira == 1)
					{
						select_mode = MODE_KIRA;
						mainReady = checkAttack(true, select_mode);
					}
					if (auto_kira == 1 && !mainReady && auto_res == 1)
					{
						select_mode = MODE_RES;
						mainReady = checkAttack(true, select_mode);
					}
					else if (auto_kira == 0 && auto_res == 1)
					{
						select_mode = MODE_RES;
						mainReady = checkAttack(true, select_mode);
					}
					if (auto_steel == 1)
					{
						select_mode = MODE_STEEL;
						mainReady = checkAttack(true, select_mode);
					}
					
					if (mainReady)
					{
						System.out.println("***主力舰队战斗准备完毕，可以出击。***");
						MainWindow.log("***战斗准备完毕***");
					}
					bgLeftClick(120, 120);
					rDelay(1500);
					bgLeftClick(700, 440);
				}
				System.out.println("等待返回母港。");
				MainWindow.log("等待返回母港。");
				rDelay(3000);
				if (!waitForColor("FFA29F20", 767, 442, 40, 40))
				{
					reconnect(1);
					continue;
				}
				System.out.println("补给完毕，返回母港。");
				MainWindow.log("补给完毕，返回母港");
				rDelay(3000);
				
				// attack_back_wait
				System.out.println("正在检查舰队归还状态");
				MainWindow.log("正在检查舰队归还");
				
				if (!waitForColor("FFFDFEFF", 377, 45, 740, 432))
				{
					reconnect(1);
					continue;
				}
				rDelay(500);
			
				if (command.isColor(hwnd, "FFAFB626", 523, 30))
				{
					System.out.println("发现舰队归还，正在处理");
					MainWindow.log("发现舰队归还，正在处理");
					for (int i = 0; i < 30; i++)
					{
						bgLeftClick(740, 432);
						rDelay(1000);
					}
					continue;
				}
				
				if (mission_id == 0 && (auto_mode == 1 || auto_kira == 1 || auto_res == 1 || auto_steel == 1) && mainReady)
				{
					rDelay(500);
					System.out.println("***主力舰队，出击准备！***");
					MainWindow.log("主力舰队，出击准备");
					bgLeftClick(200, 250);
					rDelay(2500);
					System.out.println("进入出击界面");
					bgLeftClick(240, 220);
					if (!waitForColor("FF234A5F", 133, 118, 133, 118))
					{
						reconnect(1);
						continue;
					}
					
					rDelay(2000);
					
					if (select_mode == MODE_KIRA)
					{
						System.out.println("选择地图中，1-1");
						bgLeftClick(220, 200);
						rDelay(1500);
						bgLeftClick(670, 440);
					}		
					else if (select_mode == MODE_LEVEL)
					{
						if (auto_map == "3-2")
						{
							System.out.println("选择地图中，3-2");
							bgLeftClick(309, 442);
							rDelay(1000);
							bgLeftClick(600, 200);	
							rDelay(1500);
							bgLeftClick(670, 440);
						}
						else if (auto_map == "5-4")
						{
							System.out.println("选择地图中，5-4");
							bgLeftClick(450, 442);
							rDelay(1000);
							bgLeftClick(600, 350);	
							rDelay(1500);
							bgLeftClick(670, 440);
						}
						
						refreshInfo();
						//rDelay(2000);
						System.out.println("正在进行最后确认");
						MainWindow.log("正在进行最后确认");
						mainReady = checkAttack(false, MODE_LEVEL);
					}
					else if (select_mode == MODE_RES)
					{
						if (res_map == "2-3")
						{
							System.out.println("选择地图中，2-3");
							bgLeftClick(234, 444);
							rDelay(2000);
							bgLeftClick(282, 353);	
							rDelay(2500);
							bgLeftClick(670, 440);
						}
						else if (res_map == "1-4")
						{
							System.out.println("选择地图中，1-4");
							bgLeftClick(600, 350);	
							rDelay(1500);
							bgLeftClick(670, 440);
						}
					}
					else if (select_mode == MODE_STEEL)
					{
						System.out.println("选择地图中，3-2");
						bgLeftClick(309, 442);
						rDelay(2000);
						bgLeftClick(600, 200);	
						rDelay(2500);
						bgLeftClick(670, 440);
					}
					
					if (mainReady)
					{
						System.out.println("***主力舰队出击！***");
						MainWindow.log("***主力舰队出击！***");
						rDelay(2000);
						bgLeftClick(620, 450);
						rDelay(5000);
						
						if (auto_kira == 1 || auto_res == 1)
						{
							if (!waitForBattle("FFA29F20", 767, 442, 300, 250, 747, 426))
							{
								reconnect(1);
								continue;
							}
						}
						else if (auto_mode == 1)
						{
							if (!waitForBattle("FFA29F20", 767, 442, 495, 198, 747, 426))
							{
								reconnect(1);
								continue;
							}
						}
					}
				}
				else if (mission_id > 0)
				{
					rDelay(500);
					System.out.println("第" + fleetIndex + "舰队, 远征" + mission_id + "准备中");
					MainWindow.log("第" + fleetIndex + "舰队, 远征" + mission_id + "准备中");
					bgLeftClick(200, 260);
					rDelay(2000);
					System.out.println("进入远征中");
					MainWindow.log("进入远征中");
					bgLeftClick(660, 220);
					rDelay(2000);
					System.out.println("选择任务中");
					if (mission_id > 32)
					{
						mission_id = mission_id - 32;
						bgLeftClick(390, 440);
						rDelay(4000);
					}
					if (mission_id > 16)
					{
						mission_id = mission_id - 16;
						bgLeftClick(280, 440);
						rDelay(4000);
					}
					else if (mission_id > 8)
					{
						mission_id = mission_id - 8;
						bgLeftClick(210, 440);
						rDelay(4000);
					}
				    int missionY = 170 + (mission_id - 1) * 33;
				    if (mission_id == 8 || mission_id == 7)
				    	missionY -= 10;
					bgLeftClick(330, missionY);
					rDelay(3000);
					if (!command.isColor(hwnd, "FF4BF3FD", 606, 431))
					{
						System.out.println("确认任务中");
						MainWindow.log("确认任务中");
						bgLeftClick(670, 444);
						rDelay(3000);
						System.out.println("选择舰队中");
						bgLeftClick(365 + (fleetIndex - 1) * 30, 120, 2);
						rDelay(3000);
						if (!command.isColor(hwnd, "FF12621B", 476, 173))
						{
							System.out.println("正在出击");
							MainWindow.log("正在出击");
							bgLeftClick(670, 444);
						}
						System.out.println("等待返回母港。");
						MainWindow.log("等待返回母港");
						rDelay(5000);
					}
					else
					{
						System.out.println("远征已经出发，结束流程");
						MainWindow.log("远征已经出发，结束流程");
					}
					
					if (!waitForColor("FFA29F20", 767, 442, 40, 40))
					{
						reconnect(1);
						continue;
					}
					
					System.out.println("远征出击完毕，返回母港。");
					MainWindow.log("远征出击完毕");
					rDelay(3000);
				}
				else
				{
					System.out.println("自主规制等待中。");
					MainWindow.log("自主规制等待中");
					rDelay(60000);
				}
					
				// This is error fix.
				if (!waitForColor("FFA29F20", 767, 442, 40, 40))
				{
					reconnect(1);
					continue;
				}
				reconnect(0);
			}
			catch (Exception e)
			{
				e.printStackTrace();
				try {
					reconnect(1);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	// 2.0 ok
	private boolean checkAttack(boolean fix, int mode) throws InterruptedException
	{
		int isReady = 0;

		for (int i = 0; i < 6; i++)
			if (shipReady(fleetData[fleetIndex][i], i, fix, mode))
				isReady++;

		return (isReady == 6);
	}
	
	// 2.0 ok
	private boolean shipReady(int shipId, int ruleId, boolean fix, int mode) throws InterruptedException
	{
		if (shipId == -1 && (mode == MODE_KIRA || mode == MODE_RES || mode == MODE_STEEL))
			return true;
		
		TurnRule thisRule = null;
		
		if (mode == MODE_KIRA)
		{
			thisRule = kiraRule;
			ruleId = 0;
		}
		else if (mode == MODE_RES)
		{
			thisRule = resRule;
			ruleId = 0;
		}
		else if (mode == MODE_LEVEL)
		{
			thisRule = rules[ruleId];
		}
		else if (mode == MODE_MISSION)
		{
			thisRule = missionRule[fleet_mission_map[fleetIndex]][ruleId];
		}
		else if (mode == MODE_STEEL)
		{
			thisRule = feedRule;
			ruleId = 0;
		}
		
		boolean isReady = false;
		Ship ship = ships.get(shipId);
		if (ship == null)
			isReady = false;
		else 
		{
			for (int f = 1; f <= 4; f++)
			{
				for (int i = 0; i < 6; i++)
				{
					if (fleetData[f][i] == shipId)
					{
						ship.nowFleet = f;
						ship.nowIndex = i;
					}
				}
			}
			/*
			System.out.println("id:" + ship.id);
			System.out.println("fleetIndex:" + fleetIndex);
			System.out.println("ruleId:" + ruleId);
			System.out.println("nowFleet:" + ship.nowFleet);
			System.out.println("nowIndex:" + ship.nowIndex);*/
			
			if (shipId == -1 && thisRule.turnNum > 0)
			{
				System.out.println("位置" + ruleId + " 无舰娘，准备配置。");
				MainWindow.log("位置" + ruleId + " 无舰娘，准备配置。");
			}
			else if (!thisRule.inTurn(shipId))
			{
				System.out.println("位置" + ruleId + " 舰娘不在规则中，进行替换。");
				MainWindow.log("位置" + ruleId + " 舰娘不在规则中，进行替换。");
			}
			else if (ship.inDock)
			{
				System.out.println(getShipName(shipId) + "修理中，无法出击。");
				MainWindow.log(getShipName(shipId) + "修理中，无法出击。");
				isReady = false;
			}
			else if ((mode == MODE_LEVEL || mode == MODE_KIRA || mode == MODE_RES) && ship.nowFleet > 1)
			{
				System.out.println(getShipName(shipId) + " 在远征舰队，无法出击。");
				MainWindow.log(getShipName(shipId) + " 在远征舰队，无法出击。");
				isReady = false;
			}
			else if (mode == MODE_MISSION && (ship.nowFleet > 0 && (ship.nowFleet != fleetIndex || ship.nowIndex != ruleId)))
			{
				System.out.println(getShipName(shipId) + " 已在舰队中安排位置，无法出击。");
				MainWindow.log(getShipName(shipId) + " 已在舰队中安排位置，无法出击。");
				isReady = false;
			}
			else if (ship.lv >= thisRule.lvGate)
			{
				System.out.println(getShipName(shipId) + " 等级达到 " + ship.lv + "，停止出击。");
										MainWindow.log(getShipName(shipId) + " 等级达到 " + ship.lv + "，停止出击。");
				isReady = false;
			}
			else if (ship.perHp <= thisRule.hpGate)
			{
				System.out.println(getShipName(shipId) + "耐久" + ship.nowHp + "/" + ship.maxHp + " 无法出击。准备维修。");
				MainWindow.log(getShipName(shipId) + "耐久" + ship.nowHp + "/" + ship.maxHp + " 无法出击。准备维修。");
				System.out.println("预计时间：" + ship.ndockTime / 1000 / 60 + "min");
				rDelay(1500);
				if ((ship.ndockTime > 5000000 && auto_mode == 1))
				{
					MainWindow.log("**使用快速修理**");
					repairShip(shipId, 1, 0);
				}
				else
					repairShip(shipId, 0, auto_res);
				
				isReady = false;
			}
			else if ((mode == MODE_LEVEL || mode == MODE_MISSION || mode == MODE_RES) && ship.cond < thisRule.condGate)
			{
				System.out.println(getShipName(shipId) + "疲劳" + ship.cond + "<" + thisRule.condGate + " 无法出击。");
				MainWindow.log(getShipName(shipId) + "疲劳" + ship.cond + "<" + thisRule.condGate + " 无法出击。");
				isReady = false;
			}
			else if (mode == MODE_KIRA && ship.cond >= thisRule.condGate)
			{
				System.out.println(getShipName(shipId) + "\t疲劳" + ship.cond + ">=" + thisRule.condGate + " 刷闪完成。");
				MainWindow.log(getShipName(shipId) + "\t疲劳" + ship.cond + ">=" + thisRule.condGate + " 刷闪完成。");
				if (ship.nowHp < ship.maxHp)
					repairShip(ship.id, 0, 1);
				isReady = false;
			}
			else
			{
				System.out.println(getShipName(shipId) + "\t疲劳" + ship.cond + "\t耐久" + ship.nowHp + "/" + ship.maxHp + ":" + ((int)(ship.perHp * 100)) + "%" + "\t可以出击。");
				MainWindow.log(getShipName(shipId) + "\t疲劳" + ship.cond + "\t耐久" + ship.nowHp + "/" + ship.maxHp + ":" + ((int)(ship.perHp * 100)) + "%" + "\t可以出击。");
				isReady = true;
			}
		}
		
		if (!isReady && fix)
		{
			for (int i = 0; i < thisRule.turnNum; i++)
			{
				int turnId = thisRule.getShip(i);
				if (turnId > 0 && turnId != shipId && shipReady(turnId, ruleId, false, mode))
				{
					System.out.println(getShipName(turnId) + "\t检查通过，根据规则" + ruleId + "进行轮换");
					MainWindow.log(getShipName(turnId) + "\t检查通过，根据规则" + ruleId + "进行轮换");
					rDelay(1000);
					if (mode == MODE_KIRA || mode == MODE_RES)
					{
						System.out.println(getShipName(turnId) + "\t正在更换兵装");
						MainWindow.log(getShipName(turnId) + "\t正在更换兵装");
						changeShip(fleetIndex, ruleId, turnId);
						rDelay(3000);
						changeEquip(turnId, 0, 9374);
						rDelay(3000);
						changeEquip(turnId, 1, 10236);
						rDelay(2000);
					}
					else
					{
						changeShip(fleetIndex, ruleId, turnId);
						rDelay(2000);
					}
					isReady = true;
					break;
				}
			}
		}
		return isReady;
	}
	
	// 2.0 done
	private void refreshInfo()
	{
		/*
		token = command.getToken(hwnd, memOffset);
		System.out.println(token);
		api_port_port(null);*/
	}
	
	private void checkFeedShips()
	{
		feedRule.clearShip();
		for (Ship ship : ships.values())
		{
			if (ship.lv < 10 && ship.id > 7432 && ship.locked == 0 && ship.maxHp < 20)
			{
				System.out.print(ship.id + ",");
				feedRule.addShip(ship.id);
			}
		}
		System.out.println();
	}
	
	// 2.0 done
	private void repairShip(int id, int highspeed, int unequip) throws InterruptedException
	{
		if (ships.get(id).inDock)
			return;
		for (int i = 1; i <= 4; i++)
			if (ndockStatus[i] == id)
				return;

		if (ships.get(id).slot[0] > 0 && unequip == 1 && !ships.get(id).inDock)
		{
			changeEquip(id, 0, -1);
			rDelay(3000);
			if (ships.get(id).slot[1] > 0)
			{
				changeEquip(id, 0, -1);
				rDelay(2000);
			}
		}
		
		int ndock_id;
		for (ndock_id = 1; ndock_id <= 4; ndock_id++)
			if (ndockStatus[ndock_id] == 0)
				break;
		if (ndock_id >= 1 && ndock_id <= 4)
		{
			api_req_nyukyo_start(id, highspeed, ndock_id);
			api_get_member_ndock();
			ships.get(id).inDock = true;
		}
	}
	
	// 2.0 done
	private void changeShip(int fleet, int index, int id) throws InterruptedException
	{
		int oldShipId = 0;
		oldShipId = fleetData[fleet][index];
		api_req_hensei_change(fleet, index, id);
		if (oldShipId > 0)
		{
			ships.get(id).nowFleet = -1;
			ships.get(id).nowIndex = -1;
			if (auto_res == 1 && ships.get(oldShipId).slot[0] > 0 && !ships.get(oldShipId).inDock)
			{	
				changeEquip(oldShipId, 0, -1);
				rDelay(3000);
				if (ships.get(oldShipId).slot[1] > 0)
				{
					changeEquip(oldShipId, 0, -1);
					rDelay(2000);
				}
			}
		}
		fleetData[fleet][index] = id;
		ships.get(id).nowFleet = fleet;
		ships.get(id).nowIndex = index;
	}
	
	// 2.0 done
	private void changeEquip(int id, int slot, int item_id)
	{
		api_req_kaisou_slotset(id, slot, item_id);
		api_get_member_ship3((item_id == -1)?id:0);

	}
	
	public void resetCount()
	{
		startTime = System.currentTimeMillis();
		for (int i = 0; i < 7; i++)
		{
			startResource[i] = resource[i];
		}
		for (int i = 0; i < 3; i++)
		{
			startWldata[i] = wldata[i];
		}
		
		PropertyHelper.writeProperties("fleet_status_start_time", Long.toString(startTime));
		PropertyHelper.writeProperties("fleet_status_win", Integer.toString(startWldata[0]));
		PropertyHelper.writeProperties("fleet_status_lose", Integer.toString(startWldata[1]));
		PropertyHelper.writeProperties("fleet_status_bp", Integer.toString(startWldata[2]));
		PropertyHelper.writeProperties("fleet_status_oil", Integer.toString(startResource[0]));
		PropertyHelper.writeProperties("fleet_status_ammo", Integer.toString(startResource[1]));
		PropertyHelper.writeProperties("fleet_status_steel", Integer.toString(startResource[2]));
		PropertyHelper.writeProperties("fleet_status_alum", Integer.toString(startResource[3]));
		PropertyHelper.writeProperties("fleet_status_bucket", Integer.toString(startResource[5]));
		PropertyHelper.writeProperties("fleet_status_build", Integer.toString(startResource[6]));
	}
	
	public void updateCount()
	{
		MainWindow.display.asyncExec(new Runnable() 
		{
			public void run() 
			{
				SimpleDateFormat formatter = new SimpleDateFormat("MM-dd HH:mm:ss");
				Date startDate = new Date(startTime);
				String startTimeString = formatter.format(startDate);
				float eclipseHours = (float)(System.currentTimeMillis() - startTime) / 3600000;
				MainWindow.lblCountStartTime.setText(String.format("统计开始：%s", startTimeString));
				MainWindow.lblCountEclipseTime.setText(String.format("时间经过：%.01f 小时", eclipseHours));
				if (MainWindow.bCountSwitchMode == 0)
				{
					MainWindow.lblCountWin.setText(String.format("胜：%.01f", ((wldata[0] - startWldata[0]) / eclipseHours)));
					MainWindow.lblCountLose.setText(String.format("负：%.01f", ((wldata[1] - startWldata[1]) / eclipseHours)));
					MainWindow.lblCountBP.setText(String.format("战果：%.01f", ((wldata[2] - startWldata[2]) / eclipseHours / 1400)));
					MainWindow.lblCountOil.setText(String.format("油：%.01f", ((resource[0] - startResource[0]) / eclipseHours)));
					MainWindow.lblCountAmmo.setText(String.format("弹：%.01f", ((resource[1] - startResource[1]) / eclipseHours)));
					MainWindow.lblCountSteel.setText(String.format("钢：%.01f", ((resource[2] - startResource[2]) / eclipseHours)));
					MainWindow.lblCountAlum.setText(String.format("铝：%.01f", ((resource[3] - startResource[3]) / eclipseHours)));
					MainWindow.lblCountBucket.setText(String.format("桶：%.01f", ((resource[5] - startResource[5]) / eclipseHours)));
					MainWindow.lblCountBuild.setText(String.format("资：%.01f", ((resource[6] - startResource[6]) / eclipseHours)));
				}
				else 
				{
					MainWindow.lblCountWin.setText(String.format("胜：%d", ((wldata[0] - startWldata[0]))));
					MainWindow.lblCountLose.setText(String.format("负：%d", ((wldata[1] - startWldata[1]))));
					MainWindow.lblCountBP.setText(String.format("战果：%.01f", ((float)(wldata[2] - startWldata[2]) / 1400)));
					MainWindow.lblCountOil.setText(String.format("油：%d", ((resource[0] - startResource[0]))));
					MainWindow.lblCountAmmo.setText(String.format("弹：%d", ((resource[1] - startResource[1]))));
					MainWindow.lblCountSteel.setText(String.format("钢：%d", ((resource[2] - startResource[2]))));
					MainWindow.lblCountAlum.setText(String.format("铝：%d", ((resource[3] - startResource[3]))));
					MainWindow.lblCountBucket.setText(String.format("桶：%d", ((resource[5] - startResource[5]))));
					MainWindow.lblCountBuild.setText(String.format("资：%d", ((resource[6] - startResource[6]))));
				}
			}
		});
		
		/*
		System.out.println("RUN: " + timestamp 
				+ ", W: " + (MainWindow.kcs.wldata[0] - MainWindow.kcs.startWldata[0])
				+ ", L: " + (MainWindow.kcs.wldata[1] - MainWindow.kcs.startWldata[1])
				+ ", E: " + (MainWindow.kcs.wldata[2] - MainWindow.kcs.startWldata[2])
				+ ", 油: " + (MainWindow.kcs.resource[0] - MainWindow.kcs.startResource[0])
				+ ", 弹: " + (MainWindow.kcs.resource[1] - MainWindow.kcs.startResource[1])
				+ ", 钢: " + (MainWindow.kcs.resource[2] - MainWindow.kcs.startResource[2])
				+ ", 铝: " + (MainWindow.kcs.resource[3] - MainWindow.kcs.startResource[3])
				+ ", 桶: " + (MainWindow.kcs.resource[5] - MainWindow.kcs.startResource[5])
				+ ", 资: " + (MainWindow.kcs.resource[6] - MainWindow.kcs.startResource[6]));*/
		
	}
	
	// 2.0 done
	public void api_port_port(String response)
	{
		if (response == null)
		{
			params = new ArrayList<BasicNameValuePair>();
			params.add(new BasicNameValuePair("api_verno", "1"));
			params.add(new BasicNameValuePair("api_token", token));
			params.add(new BasicNameValuePair("api_port", getPortTime()));
			params.add(new BasicNameValuePair("spi_sort_order", "2"));
			params.add(new BasicNameValuePair("api_sort_key", "5"));
			response = HttpUtil.connectPost("kcsapi/api_port/port", params, referer, flashVersion);
		}
		response = response.substring(response.indexOf("=") + 1);
		
		//System.out.println(response);
		JSONObject shipJSON = new JSONObject(response);
		JSONObject userInfoJSON = shipJSON.getJSONObject("api_data").getJSONObject("api_basic");
		wldata[0] = userInfoJSON.getInt("api_st_win");
		wldata[1] = userInfoJSON.getInt("api_st_lose");
		wldata[2] = userInfoJSON.getInt("api_experience");
		
		JSONArray materialInfoJSON = shipJSON.getJSONObject("api_data").getJSONArray("api_material");
		for (int i = 0; i < 7; i++)
		{
			resource[i] = materialInfoJSON.getJSONObject(i).getInt("api_value");
		}
		
		JSONArray shipListJSON = shipJSON.getJSONObject("api_data").getJSONArray("api_ship");
		ships.clear();
		for (int i = 0; i < shipListJSON.length(); i++)
		{
			JSONObject shipDataJSON = shipListJSON.getJSONObject(i);
			Ship ship = new Ship();
			ship.id = shipDataJSON.getInt("api_id");
			ship.lv = shipDataJSON.getInt("api_lv");
			ship.nowHp = shipDataJSON.getInt("api_nowhp");
			ship.maxHp = shipDataJSON.getInt("api_maxhp");
			ship.ndockTime = shipDataJSON.getInt("api_ndock_time");
			ship.cond = shipDataJSON.getInt("api_cond");
			ship.perHp = ((double)ship.nowHp) / ((double)ship.maxHp);
			ship.inDock = false;
			ship.locked = shipDataJSON.getInt("api_locked");
			for (int dockShipId : ndockStatus)
				if (dockShipId == ship.id)
					ship.inDock = true;
			for (int s = 0; s < 5; s++)
				ship.slot[s] = shipDataJSON.getJSONArray("api_slot").getInt(s);
				
			ships.put(ship.id, ship);
			//System.out.println("id:" + ship.id + ", hp:" + ship.nowHp + "/" + ship.maxHp + ", ndock:" + ship.ndockTime + ", cond:" + ship.cond);
		}
		
		JSONArray firstFleetListJSON= shipJSON.getJSONObject("api_data").getJSONArray("api_deck_port").getJSONObject(0).getJSONArray("api_ship");
		for (int i = 0; i < 6; i++)
		{
			if (i < firstFleetListJSON.length())
				fleetData[1][i] = firstFleetListJSON.getInt(i);
			else
				fleetData[1][i] = -1;
			//System.out.println(firstFleet[i]);
		}
		for (int f = 2; f <= 4; f++)
		{
			JSONArray elseFleetListJSON= shipJSON.getJSONObject("api_data").getJSONArray("api_deck_port").getJSONObject(f-1).getJSONArray("api_ship");
			for (int i = 0; i < 6; i++)
			{
				if (i < elseFleetListJSON.length())
					fleetData[f][i] = elseFleetListJSON.getInt(i);
				else
					fleetData[f][i] = -1;
			}
		}
		
		JSONArray ndockListJSON = shipJSON.getJSONObject("api_data").getJSONArray("api_ndock");
		for (int i = 0; i < ndockListJSON.length(); i++)
		{
			JSONObject ndock = ndockListJSON.getJSONObject(i);
			ndockStatus[i + 1] = ndock.getInt("api_ship_id"); 
			//System.out.println("ndock " + (i + 1) + " : " + ndockStatus[i + 1]);
		}
		
		updateCount();
	}
	
	// 2.0 done
	private void api_req_kaisou_slotset(int id, int slot, int item_id)
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		params.add(new BasicNameValuePair("api_id", Integer.toString(id)));
		params.add(new BasicNameValuePair("api_slot_idx", Integer.toString(slot)));
		params.add(new BasicNameValuePair("api_item_id", Integer.toString(item_id)));
		response = HttpUtil.connectPost("kcsapi/api_req_kaisou/slotset", params, referer, flashVersion);
	}
	
	private void api_req_hokyu_charge(String ids)
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_kind", "3"));
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		params.add(new BasicNameValuePair("api_id_items", ids));
		params.add(new BasicNameValuePair("api_onslot", "1"));
		response = HttpUtil.connectPost("kcsapi/api_req_hokyu/charge", params, referer, flashVersion);
	}
	
	// 2.0 done
	private void api_req_hensei_change(int fleet, int index, int id)
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		params.add(new BasicNameValuePair("api_id", Integer.toString(fleet)));
		params.add(new BasicNameValuePair("api_ship_id", Integer.toString(id)));
		params.add(new BasicNameValuePair("api_ship_idx", Integer.toString(index)));
		response = HttpUtil.connectPost("kcsapi/api_req_hensei/change", params, referer, flashVersion);
	}
	
	// 2.0 done
	private void api_req_nyukyo_start(int id, int highspeed, int ndock_id)
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		params.add(new BasicNameValuePair("api_highspeed", Integer.toString(highspeed)));
		params.add(new BasicNameValuePair("api_ship_id", Integer.toString(id)));
		params.add(new BasicNameValuePair("api_ndock_id", Integer.toString(ndock_id)));
		response = HttpUtil.connectPost("kcsapi/api_req_nyukyo/start", params, referer, flashVersion);
		//System.out.println(response);
	}
	/*
	private void api_get_member_basic()
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		response = HttpUtil.connectPost("kcsapi/api_get_member/basic", params, referer);
		//response = response.substring(response.indexOf("=") + 1);
	}
	
	private void api_get_member_ship2()
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		params.add(new BasicNameValuePair("api_sort_order", "2"));
		params.add(new BasicNameValuePair("api_sort_key", "1"));
		response = HttpUtil.connectPost("kcsapi/api_get_member/ship2", params, referer);
		//response = response.substring(response.indexOf("=") + 1);
	}*/
	
	// 2.0 done
	private void api_get_member_ship3(int shipId)
	{
		if (shipId > 0)
		{
			params = new ArrayList<BasicNameValuePair>();
			params.add(new BasicNameValuePair("api_verno", "1"));
			params.add(new BasicNameValuePair("api_token", token));
			params.add(new BasicNameValuePair("spi_sort_order", "1"));
			params.add(new BasicNameValuePair("api_sort_key", "1"));
			params.add(new BasicNameValuePair("api_shipid", Integer.toString(shipId)));
			response = HttpUtil.connectPost("kcsapi/api_get_member/ship3", params, referer, flashVersion);
			//System.out.println(response);
			return;
		}
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		params.add(new BasicNameValuePair("spi_sort_order", "2"));
		params.add(new BasicNameValuePair("api_sort_key", "5"));
		response = HttpUtil.connectPost("kcsapi/api_get_member/ship3", params, referer, flashVersion);
		response = response.substring(response.indexOf("=") + 1);
		JSONObject shipJSON = new JSONObject(response);
		JSONArray shipListJSON = shipJSON.getJSONObject("api_data").getJSONArray("api_ship_data");
		ships.clear();
		for (int i = 0; i < shipListJSON.length(); i++)
		{
			JSONObject shipDataJSON = shipListJSON.getJSONObject(i);
			Ship ship = new Ship();
			ship.id = shipDataJSON.getInt("api_id");
			ship.lv = shipDataJSON.getInt("api_lv");
			ship.nowHp = shipDataJSON.getInt("api_nowhp");
			ship.maxHp = shipDataJSON.getInt("api_maxhp");
			ship.ndockTime = shipDataJSON.getInt("api_ndock_time");
			ship.cond = shipDataJSON.getInt("api_cond");
			ship.perHp = ((double)ship.nowHp) / ((double)ship.maxHp);
			ship.inDock = false;
			for (int dockShipId : ndockStatus)
				if (dockShipId == ship.id)
					ship.inDock = true;
			for (int s = 0; s < 5; s++)
				ship.slot[s] = shipDataJSON.getJSONArray("api_slot").getInt(s);
				
			ships.put(ship.id, ship);
			//System.out.println("id:" + ship.id + ", hp:" + ship.nowHp + "/" + ship.maxHp + ", ndock:" + ship.ndockTime + ", cond:" + ship.cond);
		}
	}
	
	/*
	private void api_get_member_deck_port()
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		response = HttpUtil.connectPost("kcsapi/api_get_member/deck_port", params, referer);
		//response = response.substring(response.indexOf("=") + 1);
	}
	
	// ����
	private void api_get_member_material()
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		response = HttpUtil.connectPost("kcsapi/api_get_member/material", params, referer);
		//response = response.substring(response.indexOf("=") + 1);
	}*/
	
	// 2.0 done
	private void api_get_member_ndock()
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		response = HttpUtil.connectPost("kcsapi/api_get_member/ndock", params, referer, flashVersion);
		response = response.substring(response.indexOf("=") + 1);
		//System.out.println(response);System.out.println(token);
		JSONObject ndockJSON = new JSONObject(response);
		if (!ndockJSON.isNull("api_data"))
		{
			JSONArray ndockListJSON = ndockJSON.getJSONArray("api_data");
			for (int i = 0; i < ndockListJSON.length(); i++)
			{
				JSONObject ndock = ndockListJSON.getJSONObject(i);
				ndockStatus[i + 1] = ndock.getInt("api_ship_id"); 
				//System.out.println("ndock " + (i + 1) + " : " + ndockStatus[i + 1]);
			}
		}
		else
		{
			for (int i = 0; i < 4; i++)
			{
				ndockStatus[i + 1] = 0; 
			}
		}
	}
	/*
	private void api_get_member_deck()
	{
		params = new ArrayList<BasicNameValuePair>();
		params.add(new BasicNameValuePair("api_verno", "1"));
		params.add(new BasicNameValuePair("api_token", token));
		response = HttpUtil.connectPost("kcsapi/api_get_member/deck", params, referer);
	}*/
	
	private void reconnect(int force) throws InterruptedException
	{
		// TODO
		if (force == 1 || command.isColor(hwnd, "FF20B69D", 470, 113))
		{
			System.out.println("掉线重连中。。。");
			RECT rect = new RECT();
			user32.GetWindowRect(rhwnd, rect);
			user32.MoveWindow(rhwnd, 1, 1, rect.right - rect.left, rect.bottom - rect.top, true);
			rDelay(1000);
			command.PhysicalLeftClick(rhwnd, 40, 850);
			rDelay(1000);
			command.PhysicalLeftClick(rhwnd, 760, 600);
			rDelay(10000);
			if (!waitForColor("FFA29F20", 767, 442, 598, 401))
				reconnect(1);
		}
	}
	
	private void bgLeftClick(int x, int y)
	{
		command.LeftClick(hwnd, x, y);
		//command.LeftClick(hwnd, x, y);
	}
	
	private void bgLeftClick(int x, int y, int count)
	{
		for (int i = 0; i < count; i++)
			command.LeftClick(hwnd, x, y);
	}
	
	private boolean waitForBattle(String color, int x, int y, int px, int py, int qx, int qy) throws InterruptedException
	{
		int retry = 0;
		while (true)
		{
			if (command.isColor(hwnd, color, x, y))
			{
				rDelay(3000);
				break;
			}
			else
			{
				if (command.isColor(hwnd, "FF178EFF", 29, 277))
				{
					bgLeftClick(40, 40);
					rDelay(3000);
					continue;
				}
				rDelay(1000);
				bgLeftClick(px, py);
				rDelay(1000);
				bgLeftClick(qx, qy);
				rDelay(1000);
				retry = retry + 1;
				if (retry > 999)
				{
					return false;
				}
				if (retry > 90)
				{
					bgLeftClick(40, 40);
					rDelay(5000);
					retry = 1000;
					continue;
				}
			}
		}
		return true;
	}
	
	private boolean waitForColor(String color, int x, int y, int px, int py) throws InterruptedException
	{
		int retry = 0;
		while (true)
		{
			if (command.isColor(hwnd, color, x, y))
			{
				break;
			}
			else
			{
				rDelay(500);
				bgLeftClick(px, py);
				rDelay(500);
				retry = retry + 1;
				if (retry > 100)
				{
					return false;
				}
			}
		}
		return true;
	}
	
	private String getShipName(int shipId)
	{
		String nameString = "";
		for (String keyString : NameMap.nameMap.keySet())
		{
			if (NameMap.get(keyString) == shipId)
			{
				nameString = keyString;
				break;
			}
		}
		if (nameString == "")
			nameString = Integer.toString(shipId);
		return nameString;
	}
	
	private void rDelay(int msStart) throws InterruptedException
	{
		rDelay(msStart, (int)(msStart * 0.5));
	}
	
	private void rDelay(int msStart, int msOffset) throws InterruptedException
	{
		Thread.sleep(msStart + random.nextInt(msOffset));
	}
	
	public String getPortTime()
	{
		BigInteger millNow = new BigInteger(Long.toString(System.currentTimeMillis()));
		millNow = millNow.multiply(new BigInteger("79800"));
		BigInteger millBase = millNum.multiply(new BigInteger("79800"));
		//System.out.println(millNow.toString());
		//System.out.println(millBase.toString());
		millNow = portNum.add(millBase).add(millNow.negate());
		return millNow.toString();
	}
}
